/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <pthread.h>
#include <stddef.h>
#include <string.h>
#include <GLES3/gl3.h>
#include "cmdutils.h"
#include "ffmpeg.h"
#include "libavutil/pixfmt.h"
#include "node_api.h"
#include "js_native_api.h"
#include "native_common.h"
#include "../ffmpeg_thread/ffmpeg_thread.h"
#include "../log/ohos_log.h"
#include <stdio.h>
#include <syslog.h>
#include <string.h>
#include <unistd.h>

//用于判断是否被线程更改
int FFMPEG_HANDLE_RESULT =-1;
//指令的长度
int FFMPEG_CMD_NUM = 0;
//指令的指针数组
char **exeArgvCmd;

/**
 * 异步回调数据结构
 */
struct AsyncCallbackInfo {
    napi_env env;
    napi_async_work asyncWork;
    napi_deferred deferred;
};


/**
 * 子线程回调结果
 * @param ret
 */
 void ffmpeg_callback(int ret) {
    FFMPEG_HANDLE_RESULT = ret;
}

/**
 * 从js参数中取出字符串
 * @param env
 * @param value
 * @return
 */
 char *getStringFromJS(napi_env env,napi_value value){
    char str[400];
    size_t strlength;
    napi_get_value_string_utf8(env, value, str, sizeof(str), &strlength);
     return &str[0];
}

/**
 *从特殊字符串","取出char数组
 */
 char ** getArrayFromSpecialString(char* value){
    char str[400];
    strcpy(str, value);
    char * ffmpegcmd[400];
    char * strTemp = NULL;
    char* strSplistTempP = strtok_r(str, " ", &strTemp);
    char cmd_list[400][400];
    while (strSplistTempP != NULL) {
        strcpy(cmd_list[FFMPEG_CMD_NUM], strSplistTempP);
        FFMPEG_CMD_NUM++;
        strSplistTempP = strtok_r(NULL, " ", &strTemp);
    }
    for (int i = 0; i < FFMPEG_CMD_NUM; i++) {
        ffmpegcmd[i] = cmd_list[i];
    }
    char **argvCmd = NULL;
    argvCmd = (char**)malloc(sizeof(char *)* sizeof(ffmpegcmd));
    for (int i = 0; i < FFMPEG_CMD_NUM; ++i) {
     argvCmd[i] = (char *)(ffmpegcmd[i]);
    }
    return argvCmd;
}
/**
 * 处理ffmpeg命令并回调到JS
 * @param env
 * @param info
 * @return
 */
static napi_value exeFFmpegCmd(napi_env env, napi_callback_info info)
{
    FFMPEG_HANDLE_RESULT =-1;
    FFMPEG_CMD_NUM = 0;
    size_t argc = 2;
    napi_value argv[2];
    napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
    char * cmdTemp = getStringFromJS(env,argv[0]);
    exeArgvCmd = getArrayFromSpecialString(cmdTemp);
    napi_deferred deferred;
    napi_value promise;
      // 创建promise
      NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));

      AsyncCallbackInfo* asyncCallbackInfo = new AsyncCallbackInfo {
      .env = env,
      .asyncWork = nullptr,
      .deferred = deferred,
      };

      napi_value resourceName;
      napi_create_string_latin1(env, "ffmpegCMD", NAPI_AUTO_LENGTH, &resourceName);
      // 创建异步任务队列
     napi_create_async_work(
     env, nullptr, resourceName,
     // 异步任务的回调
     [](napi_env env, void* data) {
     ffmpeg_thread_callback(ffmpeg_callback);
      ffmpeg_thread_run_cmd(FFMPEG_CMD_NUM, exeArgvCmd);
      while (true) {
        if (FFMPEG_HANDLE_RESULT !=-1) {
            break;
        }
      }
    },
   // 异步任务结束后的回调
   [](napi_env env, napi_status status, void* data) {
    AsyncCallbackInfo* asyncCallbackInfo = (AsyncCallbackInfo*)data;
    napi_value result;
    napi_create_int32(env, FFMPEG_HANDLE_RESULT, &result);
    // 触发回调
    napi_resolve_deferred(asyncCallbackInfo->env, asyncCallbackInfo->deferred, result);
    napi_delete_async_work(env, asyncCallbackInfo->asyncWork);
    delete asyncCallbackInfo;
   },
   (void*)asyncCallbackInfo, &asyncCallbackInfo->asyncWork);
   napi_queue_async_work(env, asyncCallbackInfo->asyncWork);
   return promise;
}

/**
 * 重命名文件
 */
static napi_value reFileNamePath(napi_env env, napi_callback_info info)
{
     size_t argc = 2;
     napi_value argv[2];
     napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
     char *oldFilePath = getStringFromJS(env,argv[0]);
     char tempOldFilePath[200] = { 0 };
     strcpy(tempOldFilePath,oldFilePath);
     char *newFilePath = getStringFromJS(env,argv[1]);
     int reFileResult=rename(&tempOldFilePath[0],newFilePath);
     napi_value result;
     NAPI_CALL(env, napi_create_int32(env, reFileResult, &result));
     return result;
}

/**
 * 写文件
 */
static napi_value writeFile(napi_env env, napi_callback_info info)
{
   size_t argc = 2;
   napi_value argv[2];
   napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
   char *filePath = getStringFromJS(env,argv[0]);
   char tempFilePath[200] = { 0 };
   strcpy(tempFilePath,filePath);
   FILE *fs=NULL;
   fs=fopen(&tempFilePath[0],"w");
   char *content = getStringFromJS(env,argv[1]);
   char tempContent[200] = { 0 };
   strcpy(tempContent,content);
   int reFileResult=fputs(tempContent,fs);
   fclose(fs);
   napi_value result;
   NAPI_CALL(env, napi_create_int32(env, reFileResult, &result));
   return result;
}


EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    /*
     * Properties define
     */
    napi_property_descriptor desc[] = {
        DECLARE_NAPI_FUNCTION("exeFFmpegCmd", exeFFmpegCmd),
        DECLARE_NAPI_FUNCTION("reFileNamePath", reFileNamePath),
        DECLARE_NAPI_FUNCTION("writeFile", writeFile),
        };
        NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
    return exports;
}
EXTERN_C_END

/*
 * Module define
 */
static napi_module
        mp4parserModule = {
       .nm_version = 1,
       .nm_flags = 0,
       .nm_filename = nullptr,
       .nm_register_func = Init,
       .nm_modname = "mp4parser",
       .nm_priv = ((void *)0),
       .reserved = {
        0
       },
};
/*
 * Module register function
 */
extern "C" __attribute__((constructor)) void RegisterModule(void)
{
napi_module_register(& mp4parserModule);
}